package br.com.statizo.financeiro.domain.entity.impl;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

import br.com.statizo.financeiro.domain.enums.FormaPagamento;



@Entity
@Table(name="tb_lancamento")
public class Lancamento extends EntidadeAbstrata{

	private static final long serialVersionUID = 1L;

	@Id
	@GeneratedValue
	@Column(name="ID_LANCAMENTO")
	private Long id;

	@Column(name="DT_DIVIDA")
	@Temporal(TemporalType.TIMESTAMP)
	private Calendar dataDivida;
	
	@Column(name="DT_PGTO")
	@Temporal(TemporalType.TIMESTAMP)
	private Calendar dataPagamento;
	
	@Column(name="DS_LANCAMENTO")
	private String descricao;
	
	@Column(name="DS_OBS")
	private String observacao;
	
	@Column(name="VL_LANCAMENTO")
	private double valor;
	
	@JoinColumn(name="ID_CATEGORIA", nullable = true)
	@ManyToOne
	private Categoria categoria;
	
	@JoinColumn(name="ID_CONTA")
	@ManyToOne
	private ContaCorrente conta;
	
	@JoinColumn(name="ID_CONTA_TRANSFERENCIA")
	@ManyToOne
	private ContaCorrente contaTransferencia;
	
	@JoinColumn(name="ID_CARTAO")
	@ManyToOne
	private CartaoCredito cartao;

	@Column(name="ST_PGTO")
	private boolean pago;
	
	@ManyToOne
	@JoinColumn(name="ID_PRI_PARC")
	private Lancamento primeiraParcela;
	
	@OneToMany(mappedBy="primeiraParcela")
	private List<Lancamento> parcelas = new ArrayList<Lancamento>();
	
	@Enumerated(EnumType.ORDINAL)
	@Column(name="ID_FORMA_PGTO")
	private FormaPagamento formaPagamento;
	
	@Column(name="ST_AGEND")
	private boolean agendado;

	@Column(name="ST_SALDO", nullable = false)
	private boolean saldo = false;
	
	@Override
	public Serializable getId() {
		return this.id;
	}
	
	public boolean isDespesa(){
		return this.categoria.getGrupo().isDespesa();
	}
	
	public boolean isReceita(){
		return this.categoria.getGrupo().isReceita();
	}
	
	public boolean isInvestimento(){
		if(this.categoria == null)
			return false;
		return this.categoria.getGrupo().isInvestimento();
	}

	public Calendar getDataDivida() {
		return dataDivida;
	}

	public void setDataDivida(Calendar dataDivida) {
		this.dataDivida = dataDivida;
	}

	public Calendar getDataPagamento() {
		return dataPagamento;
	}

	public void setDataPagamento(Calendar dataPagamento) {
		this.dataPagamento = dataPagamento;
	}

	public String getDescricao() {
		return descricao;
	}

	public void setDescricao(String descricao) {
		this.descricao = descricao;
		firePropertyChange("descricao", descricao, this.descricao = descricao);
	}

	public String getObservacao() {
		return observacao;
	}

	public void setObservacao(String observacao) {
		this.observacao = observacao;
	}

	public double getValor() {
		return valor;
	}

	public void setValor(double valor) {
		this.valor = valor;
	}

	public void setCategoria(Categoria tipoLancamento) {
		this.categoria = tipoLancamento;
	}
	
	public Categoria getCategoria() {
		return categoria;
	}
	
	public ContaCorrente getConta() {
		return conta;
	}

	public void setConta(ContaCorrente conta) {
		this.conta = conta;
	}
	
	public ContaCorrente getContaTransferencia() {
		return contaTransferencia;
	}
	
	public void setContaTransferencia(ContaCorrente contaTransferencia) {
		this.contaTransferencia = contaTransferencia;
	}
	
	public FormaPagamento getFormaPagamento() {
		return formaPagamento;
	}
	
	public void setFormaPagamento(FormaPagamento formaPagamento) {
		this.formaPagamento = formaPagamento;
	}
	
	public CartaoCredito getCartao() {
		return cartao;
	}
	
	public void setCartao(CartaoCredito cartao) {
		this.cartao = cartao;
	}
	
	public Lancamento getPrimeiraParcela() {
		return primeiraParcela;
	}
	
	public boolean isPago(){
		return pago;
	}
	
	public void setPago(boolean pago){
		this.pago = pago;
	}
	
	public void setAgendado(boolean agendado) {
		this.agendado = agendado;
	}
	
	public boolean isAgendado(){
		return agendado;
	}
	
	public void setParcelas(List<Lancamento> parcelas) {
		this.parcelas = parcelas;
	}
	
	public List<Lancamento> getParcelas() {
		return parcelas;
	}
	
	public void setPrimeiraParcela(Lancamento primeiraParcela) {
		this.primeiraParcela = primeiraParcela;
	}
	
	public boolean isPrimeiraParcela(){
		if(primeiraParcela != null)
			return false;
		return parcelas.size() > 0;
	}
	
	public boolean isParcela(){
		return primeiraParcela != null;
	}
	
	public boolean isSaldo(){
		return saldo;
	}
	
	public boolean isCartao(){
		return FormaPagamento.CARTAO_CREDITO.equals(formaPagamento);
	}
	
	public boolean isSaldoSaida(int mes, int ano){
		return dataPagamento.get(Calendar.YEAR) != ano ||
				dataPagamento.get(Calendar.MONTH) != mes;
	}
	
	public void setSaldo(boolean saldo){
		this.saldo = true;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((id == null) ? 0 : id.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (!super.equals(obj))
			return false;
		if (getClass() != obj.getClass())
			return false;
		Lancamento other = (Lancamento) obj;
		if (id == null) {
			if (other.id != null)
				return false;
		} else if (!id.equals(other.id))
			return false;
		return true;
	}
	
}